package info.batcloud.fanli.api.security.wexin.authentication;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.annotation.JSONField;
import info.batcloud.fanli.api.security.handler.LoginAuthenticationSuccessHandler;
import info.batcloud.fanli.core.exception.BizException;
import info.batcloud.fanli.core.repository.UserRepository;
import info.batcloud.fanli.core.repository.WeixinAccountRepository;
import info.batcloud.fanli.core.security.authentication.NoopAuthenticationManager;
import info.batcloud.fanli.core.weixin.WxaConfig;
import info.batcloud.fanli.core.weixin.domain.UserInfo;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionTemplate;

import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

@Component
public class WxaAuthenticationAuthenticationProcessingFilter extends AbstractAuthenticationProcessingFilter {

    @Inject
    private UserRepository userRepository;

    @Inject
    private WeixinAccountRepository weixinAccountRepository;

    @Inject
    private WxaConfig wxaConfig;

    @Inject
    private TransactionTemplate transactionTemplate;

    @Inject
    private LoginAuthenticationSuccessHandler loginAuthenticationSuccessHandler;

    public WxaAuthenticationAuthenticationProcessingFilter() {
        super("/login/wxa");
        setAuthenticationManager(new NoopAuthenticationManager());
        setAuthenticationDetailsSource(authenticationDetailsSource);
    }

    @PostConstruct
    public void afterPropertiesSet() {
        this.setAuthenticationSuccessHandler(loginAuthenticationSuccessHandler);
    }


    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException, IOException, ServletException {
        String json = request.getParameter("loginData");
        WxaLoginInfo wxaLoginInfo = JSON.parseObject(json, WxaLoginInfo.class);
        CloseableHttpClient client = HttpClientBuilder.create().build();
        HttpGet httpGet = new HttpGet("https://api.weixin.qq.com/sns/jscode2session?appid=" + wxaConfig.getAppid()
                + "&secret=" + wxaConfig.getSecret() + "&js_code=" + wxaLoginInfo.getCode() + "&grant_type=authorization_code");
        HttpResponse res = client.execute(httpGet);
        String result = EntityUtils.toString(res.getEntity());
        client.close();
        WeixinSession weixinSession = JSON.parseObject(result, WeixinSession.class);
        //验证getUserInfo的signature
        String signStr = wxaLoginInfo.getRawData() + weixinSession.getSessionKey();
        String checkSign = DigestUtils.sha1Hex(signStr);
        if (!checkSign.equals(wxaLoginInfo.getSignature())) {
            throw new BizException("微信登录认证失败，请联系客服进行咨询！");
        }

//        LoginUser loginUser = transactionTemplate.execute(status -> {
//            WeixinAccount weixinAccount = weixinAccountRepository.findByOpenId(weixinSession.getOpenid());
//            if (weixinAccount == null) {
//                weixinAccount = new WeixinAccount();
//                weixinAccount.setCreateTime(new Date());
//                weixinAccount.setUpdateTime(new Date());
//                weixinAccount.setLoginTimes(0);
//            }
//            UserInfo userInfo = wxaLoginInfo.getUserInfo();
//            weixinAccount.setAvatarUrl(userInfo.getAvatarUrl());
//            weixinAccount.setCity(userInfo.getCity());
//            weixinAccount.setLastLoginTime(new Date());
//            weixinAccount.setLoginTimes(weixinAccount.getLoginTimes() + 1);
//            weixinAccount.setCountry(userInfo.getCountry());
//            weixinAccount.setGender(userInfo.getGender() + "");
//            weixinAccount.setNickname(userInfo.getNickName());
//            weixinAccount.setProvince(userInfo.getProvince());
//            weixinAccount.setOpenId(weixinSession.getOpenid());
//            weixinAccount.setUnionId(weixinSession.getUnionid());
//            User user;
//            if (weixinAccount.getUserId() == null) {
//                user = new User();
//                user.setCreateTime(new Date());
//            } else {
//                user = userRepository.findOne(weixinAccount.getUserId());
//            }
//            user.setNickname(userInfo.getNickName());
//            user.setLocked(false);
//            user.setAvatarUrl(userInfo.getAvatarUrl());
//            user.setCity(userInfo.getCity());
//            user.setCountry(userInfo.getCountry());
//            user.setProvince(userInfo.getProvince());
//            user.setGender(userInfo.getGender() == 1 ? Gender.MALE : Gender.FAMALE);
//            userRepository.save(user);
//            weixinAccount.setUserId(user.getId());
//            weixinAccountRepository.save(weixinAccount);
//            LoginUser lu = securityService.loginUserByUserId(user.getId());
//            lu.setAuthPlatform(AuthPlatform.WEIXIN);
//            return lu;
//        });
//        return new UsernamePasswordAuthenticationToken(loginUser, null, GrantedAuthorityHelper.valueOf(loginUser.getAuthorities()));
        return null;
    }

    public static class WxaLoginInfo {
        private UserInfo userInfo;

        private String rawData;

        private String signature;

        private String encryptedData;

        private String iv;

        private String code;

        public String getCode() {
            return code;
        }

        public void setCode(String code) {
            this.code = code;
        }

        public UserInfo getUserInfo() {
            return userInfo;
        }

        public void setUserInfo(UserInfo userInfo) {
            this.userInfo = userInfo;
        }

        public String getRawData() {
            return rawData;
        }

        public void setRawData(String rawData) {
            this.rawData = rawData;
        }

        public String getSignature() {
            return signature;
        }

        public void setSignature(String signature) {
            this.signature = signature;
        }

        public String getEncryptedData() {
            return encryptedData;
        }

        public void setEncryptedData(String encryptedData) {
            this.encryptedData = encryptedData;
        }

        public String getIv() {
            return iv;
        }

        public void setIv(String iv) {
            this.iv = iv;
        }
    }

    public static class WeixinSession {
        private String openid;
        @JSONField(name = "session_key")
        private String sessionKey;
        private String unionid;

        public String getOpenid() {
            return openid;
        }

        public void setOpenid(String openid) {
            this.openid = openid;
        }

        public String getSessionKey() {
            return sessionKey;
        }

        public void setSessionKey(String sessionKey) {
            this.sessionKey = sessionKey;
        }

        public String getUnionid() {
            return unionid;
        }

        public void setUnionid(String unionid) {
            this.unionid = unionid;
        }
    }
}
